package com.eastfair.security.distionarydynamic;

import cn.hutool.core.collection.CollectionUtil;
import com.eastfair.annotation.annotation.dictionary.DictionaryField;
import com.eastfair.auth.dto.RoleDTO;
import com.eastfair.auth.entity.Role;
import com.eastfair.cache.projectcore.DictionaryCacheKeyBuilder;
import com.eastfair.cache.projectcore.DictionaryEnabledCacheKeyBuilder;
import com.eastfair.cache.repository.CachePlusOps;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.context.StaticContextUtil;
import com.eastfair.core.desensitization.PrivacyUtil;
import com.eastfair.core.dynamic.DynamicProxy;
import com.eastfair.core.dynamic.FieldType;
import com.eastfair.core.dynamic.FieldTypeUtil;
import com.eastfair.core.encrypt.AESEncrypt;
import com.eastfair.core.encrypt.AESEncrypt2;
import com.eastfair.core.encrypt.RSAEncrypt;
import com.eastfair.core.model.CacheHashKey;
import com.eastfair.core.utils.ClassObjectUtil;
import com.eastfair.projectcore.api.DictionaryFeign;
import com.eastfair.projectcore.entity.Dictionary;
import com.eastfair.security.constant.ValueConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

/**
 * 精简VO参数核心功能 字典
 * ligang 2020/03/20
 */
@Component
@Slf4j
public class DistionaryDynamicAnno {
    private static final Logger logger = LoggerFactory.getLogger(DistionaryDynamicAnno.class);

    private ConcurrentHashMap<String, List<Dictionary>> concurrentHashMap = new ConcurrentHashMap<>();
    //        @Autowired
//    private RedisOps redisOps;
    @Autowired
    private CachePlusOps cachePlusOps;

    @Autowired
    DictionaryFeign dictionaryFeign;

    @Autowired
    ValueConstant valueConstant;

    public void removeData() {
        //并发
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(() -> {
            for (; ; ) {
                for (String key : concurrentHashMap.keySet()) {
                    CacheHashKey typeKey = new DictionaryEnabledCacheKeyBuilder().hashFieldKey(key, key);
                    String value = cachePlusOps.get(typeKey.getKey() + ":" + StaticContextUtil.getStaticProjectWorkId());
                    if (StringUtils.isBlank(value)) {
                        concurrentHashMap.remove(key);
                    }
                }
                Thread.sleep(10 * 1000);
            }
        });
    }

    /**
     * 精简VO实体
     *
     * @param obj ligang 2020/03/20
     */
    public Object executeSimplVo(Object obj) {
        try {
            if (obj == null) {
                return obj;
            }
            //JAVA泛型
//            Class c = FieldTypeUtil.getClassByFidldType(obj.getClass());
            Class c = FieldTypeUtil.getClassByJavaGenericity(obj.getClass());
            if (c == null) {
                //VO业务类
//                if (FieldTypeUtil.getClassByBusinList(obj.getClass()) != null) {
                //业务对象
                disposeDataByResponBody(obj);
//                }
            } else {
                if (FieldType.LIST.getTargerClazz().getName().equals(c.getName())) {
                    List list = (List) obj;
                    //List数组
                    list.forEach((s -> {
                        disposeDataByResponBody(s);
//                        Class childClass = FieldTypeUtil.getClassByJavaGenericity(s.getClass());
//                        if (childClass == null && FieldTypeUtil.getClassByBusinList(s.getClass()) != null) {
//                            disposeDataByResponBody(s);
//                        }
                    }));

                } else if (FieldType.SET.getTargerClazz().getName().equals(c.getName())) {
                    //Set数组
                } else {
                    //非业务对象，也非对象，可能就是java基本类型
                }
            }
            return obj;
        } catch (Exception e) {
            logger.info("精简VO实体失败");
            return obj;
        }
    }


    /**
     * Vo处理清空对象非必须属性
     *
     * @param obj
     */
    public Object disposeDataByResponBody(Object obj) {

        //如果遇到Enum类，不处理
        if ("java.lang.Enum".equals(obj.getClass().getSuperclass().getName())) {
            return obj;
        }

        Field[] fields = obj.getClass().getDeclaredFields();
        //有标识的深入清空
        for (Field field : fields) {
            if (FieldType.LIST.getTargerClazz().getName().equals(field.getType().getName())) {
                //List数组
                List list = (List) DynamicProxy.voInvokGetlByField(field, obj);
                if (list != null) {
                    list.forEach((s -> {
                        Class childClass = FieldTypeUtil.getClassByJavaGenericity(s.getClass());
                        if (childClass == null && FieldTypeUtil.getClassByBusinList(s.getClass()) != null) {
                            disposeDataByResponBody(s);
                        }
                    }));
                }
            } else {
                Object fieldObj1 = DynamicProxy.voInvokGetlByField(field, obj);
                if (fieldObj1 != null && FieldTypeUtil.getClassByBusinList(fieldObj1.getClass()) != null) {
                    executeSimplVo(fieldObj1);
                } else {
                    //赋值字典
                    DictionaryField dictionaryField = field.getAnnotation(DictionaryField.class);
                    if (dictionaryField != null) {
                        invokDistionaryField(obj, field, dictionaryField);
                    }
                    invokDesensitizerField(obj, field);
                }


            }
        }
        return obj;
    }

    public Object invokDistionaryField(Object obj, Field field1, DictionaryField dictionaryField) {

        //获取code值
        Object fieldObj2 = DynamicProxy.voInvokGetlByField(field1, obj);
        if (fieldObj2 == null) {
            return obj;
        }
        String type = dictionaryField.type();
//        log.info("执行查询字典操作type is {}",type);
        List<Dictionary> objectList = null;
        if (concurrentHashMap.get(type) != null) {
            objectList = concurrentHashMap.get(type);
        } else {
            log.info("执行查询字典操作 找缓存 type is {}", type);
            CacheHashKey typeKey = new DictionaryCacheKeyBuilder().hashFieldKey(type, Dictionary.class.getName());
            objectList = cachePlusOps.hGet(typeKey);
            if (objectList == null || objectList.isEmpty()) {
                R<List<Dictionary>> listR = dictionaryFeign.queryDict(type);
                if (listR.getIsSuccess()) {
                    objectList = listR.getData();
                }
            }
//            if (objectList != null && !objectList.isEmpty()) {
            concurrentHashMap.put(type, objectList);
            addCacheEnabled(type);
//            }
        }
        if (objectList == null || objectList.isEmpty()) {
            return obj;
        }
        for (Dictionary dictionary1 : objectList) {
            if (dictionary1.getCode().equals(fieldObj2 + "")) {
                //赋值
                invokEchoMapField(obj, field1.getName(), dictionary1.getName());
//                DynamicProxy.voInvokSetByField(field1, obj, dictionary.getName());
            }
        }
        return obj;
    }

    //执行更新缓存
    public void addCacheEnabled(String type) {
        CacheHashKey typeKey = new DictionaryEnabledCacheKeyBuilder().hashFieldKey(type, type, StaticContextUtil.getStaticProjectWorkId());
        cachePlusOps.set(typeKey, "1");
    }

    public Object invokDesensitizerField(Object obj, Field field1) {
        if ("1".equals(ContextUtil.getDisenstizerEnabled())) {
            if (String.class.equals(field1.getType())) {
                if ((CollectionUtil.isNotEmpty(valueConstant.getIdCarFiles()) &&
                        valueConstant.getIdCarFiles().contains(field1.getName())) ||

                        (CollectionUtil.isNotEmpty(valueConstant.getMobileFiles()) &&
                                valueConstant.getMobileFiles().contains(field1.getName())) ||

                        (CollectionUtil.isNotEmpty(valueConstant.getEmailFiles()) &&
                                valueConstant.getEmailFiles().contains(field1.getName())) ||

                        (CollectionUtil.isNotEmpty(valueConstant.getNameFiles()) &&
                                valueConstant.getNameFiles().contains(field1.getName()))

                ) {
                    String value = encryptStr(obj, field1);
                    if (StringUtils.isNotBlank(value)) {
                        DynamicProxy.voInvokSetByField(field1, obj, value);
                    }
                }

//                if (CollectionUtil.isNotEmpty(valueConstant.getIdCarFiles()) &&
//                        valueConstant.getIdCarFiles().contains(field1.getName())) {
//                    //身份证脱敏
//                    String value = privacyStr(obj, field1, 1);
//                    if (StringUtils.isNotBlank(value)) {
//                        DynamicProxy.voInvokSetByField(field1, obj, value);
//                    }
//
//                } else if (CollectionUtil.isNotEmpty(valueConstant.getMobileFiles()) &&
//                        valueConstant.getMobileFiles().contains(field1.getName())) {
//                    //手机号脱敏
//                    String value = privacyStr(obj, field1, 2);
//                    if (StringUtils.isNotBlank(value)) {
//                        DynamicProxy.voInvokSetByField(field1, obj, value);
//                    }
//                } else if (CollectionUtil.isNotEmpty(valueConstant.getEmailFiles()) &&
//                        valueConstant.getEmailFiles().contains(field1.getName())) {
//                    //邮箱脱敏
//                    String value = privacyStr(obj, field1, 3);
//                    if (StringUtils.isNotBlank(value)) {
//                        DynamicProxy.voInvokSetByField(field1, obj, value);
//                    }
//                } else if (CollectionUtil.isNotEmpty(valueConstant.getNameFiles()) &&
//                        valueConstant.getNameFiles().contains(field1.getName())) {
//                    //姓名脱敏
//                    String value = privacyStr(obj, field1, 4);
//                    if (StringUtils.isNotBlank(value)) {
//                        DynamicProxy.voInvokSetByField(field1, obj, value);
//                    }
//                }
            }
        }
        return obj;
    }

    public String privacyStr(Object obj, Field field, int type) {
        //获取值
        Object objectData = DynamicProxy.voInvokGetlByField(field, obj);
        if (objectData != null) {
            //1身份证 2手机号 3邮箱 4姓名
            if (type == 1) {
                return PrivacyUtil.hideIDCard((String) objectData);
            } else if (type == 2) {
                return PrivacyUtil.hidePhone((String) objectData);
            } else if (type == 3) {
                return PrivacyUtil.hideEmail((String) objectData);
            } else if (type == 4) {
                return PrivacyUtil.hideChineseName((String) objectData);
            }
            //赋值
//            DynamicProxy.voInvokSetByField(field, obj, objectData);
        }
        return null;
    }


    public String encryptStr(Object obj, Field field) {
        //获取值
        Object objectData = DynamicProxy.voInvokGetlByField(field, obj);
        if (objectData != null) {
            //1身份证 2手机号 3邮箱 4姓名
            try {
//                return AESEncrypt2.encrypt((String) objectData, valueConstant.getAeskey(), valueConstant.getAeskey());
                return RSAEncrypt.encrypt((String) objectData, valueConstant.getSensitivityPublicKey());
            } catch (Exception e) {
                e.printStackTrace();
                return (String) objectData;
            }
            //赋值
//            DynamicProxy.voInvokSetByField(field, obj, objectData);
        }
        return null;
    }

    /**
     * 给echoMap赋值
     *
     * @param obj
     * @param type
     * @param value
     */
    public void invokEchoMapField(Object obj, String type, String value) {
        Field[] fields = obj.getClass().getDeclaredFields();
        Object fieldObj2 = ClassObjectUtil.getFieldValueByName("echoMap", obj);
        Map<String, Object> echoMap = (Map<String, Object>) fieldObj2;
        if (echoMap == null) {
            echoMap = new HashMap<String, Object>();
        }
        echoMap.put(type, value);
        //查询是否是空
        try {
            Method m = obj.getClass().getMethod("setEchoMap", Map.class);
            Object[] dataObj = new Object[1];
            dataObj[0] = echoMap;
            m.invoke(obj, dataObj);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }


//        for (Field field2 : fields) {
//            String file2Name = field2.getName();
//            if ("echoMap".equals(field2.getName())) {
//                Object fieldObj2 = DynamicProxy.voInvokGetlByField(field2, obj);
//                Map<String, Object> echoMap = (Map<String, Object>) fieldObj2;
//                echoMap.put(type, value);
//            }
//        }
    }

}
